/*
 * Copyright (C) 2018 Zhejiang xiaominfo Technology CO.,LTD.
 * All rights reserved.
 * Official Web Site: http://www.xiaominfo.com.
 * Developer Web Site: http://open.xiaominfo.com.
 */

package com.github.xiaoymin.map.ext;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.github.xiaoymin.map.MapClientConfig;
import com.github.xiaoymin.map.exception.MapClientException;
import com.github.xiaoymin.map.http.PoolingConnectionManager;
import com.google.gson.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 各个地图厂商的基础类
 * @author <a href="mailto:xiaoymin@foxmail.com">xiaoymin@foxmail.com</a>
 * 2020/09/21 13:39
 * @since:map-client 1.0
 */
public abstract class AbstractMapClient extends PoolingConnectionManager {

    private Logger logger= LoggerFactory.getLogger(AbstractMapClient.class);

    protected final Gson gson=new GsonBuilder().create();
    protected final JsonParser jsonParser=new JsonParser();

    protected final MapClientConfig mapClientConfig;

    /**
     * 根据开发配置构造MapClient
     * @param mapClientConfig 开发配置
     */
    protected AbstractMapClient(MapClientConfig mapClientConfig) {
        this.mapClientConfig = mapClientConfig;
    }

    /**
     * 非空对象断言
     * @param param 对象
     */
    protected void assertNotEmpty(Object param){
        assertNotEmpty(param,"请求参数对象不能为空");
    }

    /**
     * 非空对象断言
     * @param param 对象
     * @param err 错误信息
     */
    protected void assertNotEmpty(Object param,String err){
        if (param==null){
            throw new MapClientException(err);
        }
    }

    /**
     * 添加默认请求头
     * @param httpRequest 请求类型
     * @param headers 请求头
     */
    protected void addDefaultHeader(HttpRequest httpRequest, Map<String,String> headers){
        if (CollectionUtil.isNotEmpty(headers)){
            for (Map.Entry<String,String> header:headers.entrySet()){
                httpRequest.addHeader(header.getKey(),header.getValue());
            }
        }
    }

    /**
     * 添加请求头
     * @param httpRequest 请求对象
     * @param headerName header名称
     * @param headerValue header值
     */
    protected void addDefaultHeader(HttpRequest httpRequest,String headerName,String headerValue){
        if (StrUtil.isNotBlank(headerName)){
            httpRequest.addHeader(headerName,headerValue);
        }
    }
    /**
     * 构造form请求参数的实体
     * @param params 参数
     * @return 请求http实体
     */
    protected HttpEntity buildFormEntity(Map<String,String> params){
        List<NameValuePair> nameValuePairs=new ArrayList<>();
        for (Map.Entry<String,String> entry:params.entrySet()){
            nameValuePairs.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));
        }
        try {
            UrlEncodedFormEntity urlEncodedFormEntity=new UrlEncodedFormEntity(nameValuePairs,"utf-8");
            return urlEncodedFormEntity;
        } catch (UnsupportedEncodingException e) {
            //nothing
        }
        return null;
    }

    /**
     * 获取返回接口
     * @param httpUriRequest 请求request
     * @param clazz 反射类
     * @param <T> 泛型对象
     * @return optional对象
     */
    protected <T> Optional<T> execute(HttpUriRequest httpUriRequest,Class<T> clazz){
        String content=execute(httpUriRequest);
        if (StrUtil.isNotBlank(content)){
            return Optional.ofNullable(gson.fromJson(content,clazz));
        }
        return Optional.empty();
    }

    /**
     * 执行HTTP请求
     * @param httpUriRequest 请求实体
     * @return 返回HTTP-content
     */
    protected String execute(HttpUriRequest httpUriRequest){
        logger.debug("执行URI:{},Method:{}",httpUriRequest.getURI(),httpUriRequest.getMethod());
        CloseableHttpClient client=getClient();
        try {
            CloseableHttpResponse response=client.execute(httpUriRequest);
            if (response!=null){
                int statusCode=response.getStatusLine().getStatusCode();
                logger.debug("状态码:{}",statusCode);
                if (statusCode== HttpStatus.SC_OK){
                    String content= EntityUtils.toString(response.getEntity(),"UTF-8");
                    logger.debug("Content:{}",content);
                    return content;
                }
            }
        } catch (IOException e) {
            logger.error("执行HTTP方法错误,err:"+e.getMessage(),e);
        }finally {
            closeQuietly(client);
        }
        return null;
    }

}
